package main

import (
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/rpc"
	"sync"
	"time"

	"gitee.com/distribute_system/heartbeats/idl"
	"gitee.com/distribute_system/heartbeats/utils"
)

const (
	Address = "127.0.0.1"
	Port    = ":6789"
)

type ClientInfo struct {
	Node             *idl.NodeInfo
	LastActivateTime time.Time
}

type Service struct {
	ClientList sync.Map
}

func (s *Service) Ping(req idl.HeartBeatsRequest, resp *idl.HeartBeatsResponse) (err error) {
	if req.Info == nil {
		return errors.New("参数错误")
	}

	client := ClientInfo{
		Node:             req.Info,
		LastActivateTime: time.Now(),
	}
	fmt.Println("[HeartBeats] Client Register, addres: " + req.Info.Address)
	s.ClientList.Store(req.Info.Address, &client)
	return nil
}

func (s *Service) RemoveDeadClient() {
	now := time.Now()

	s.ClientList.Range(func(key, value interface{}) bool {
		v := value.(*ClientInfo)
		if now.Sub(v.LastActivateTime) > 10*time.Second {
			// 超过5s未收到心跳，清除节点
			fmt.Printf("Node %v Removed.\n", key)
			s.ClientList.Delete(key)
		}
		return true
	})
}

func main() {
	service := new(Service)

	utils.ScheduleAtFixedRate(func() {
		service.RemoveDeadClient()
	}, 0, 10, time.Second)

	rpc.Register(service)
	rpc.HandleHTTP()

	l, err := net.Listen("tcp", Address+Port)
	if err != nil {
		panic(err)
	}

	fmt.Println("Service Start At Port " + Port)
	http.Serve(l, nil)
}
